package me.zhengjie.modules.business.service.impl;

import me.zhengjie.modules.business.domain.AuthData;
import me.zhengjie.modules.business.domain.WxUser;
import me.zhengjie.modules.business.repository.AuthDataRepository;
import me.zhengjie.modules.business.repository.WxUserRepository;
import me.zhengjie.modules.business.service.AuthDataService;
import me.zhengjie.modules.business.service.dto.AuthDataDto;
import me.zhengjie.modules.business.service.dto.AuthDataQueryCriteria;
import me.zhengjie.modules.business.service.mapper.AuthDataMapper;
import me.zhengjie.utils.FileUtil;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.QueryHelp;
import me.zhengjie.utils.ValidationUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

// 默认不使用缓存
//import org.springframework.cache.annotation.CacheConfig;
//import org.springframework.cache.annotation.CacheEvict;
//import org.springframework.cache.annotation.Cacheable;

/**
* @author churuitao
* @date 2020-02-02
*/
@Service
//@CacheConfig(cacheNames = "authData")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class AuthDataServiceImpl implements AuthDataService {

    private final AuthDataRepository authDataRepository;

    private final AuthDataMapper authDataMapper;

    private final WxUserRepository wxUserRepository;

    public AuthDataServiceImpl(AuthDataRepository authDataRepository, AuthDataMapper authDataMapper, WxUserRepository wxUserRepository) {
        this.authDataRepository = authDataRepository;
        this.authDataMapper = authDataMapper;
        this.wxUserRepository = wxUserRepository;
    }

    @Override
    //@Cacheable
    public Map<String,Object> queryAll(AuthDataQueryCriteria criteria, Pageable pageable){
        Page<AuthData> page = authDataRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return PageUtil.toPage(page.map(authDataMapper::toDto));
    }

    @Override
    //@Cacheable
    public List<AuthDataDto> queryAll(AuthDataQueryCriteria criteria){
        return authDataMapper.toDto(authDataRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    //@Cacheable(key = "#p0")
    public AuthDataDto findById(Integer id) {
        AuthData authData = authDataRepository.findById(id).orElseGet(AuthData::new);
        ValidationUtil.isNull(authData.getId(),"AuthData","id",id);
        return authDataMapper.toDto(authData);
    }

    @Override
    //@CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public AuthDataDto create(AuthData resources) {
        return authDataMapper.toDto(authDataRepository.save(resources));
    }

    @Override
    //@CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public void update(AuthData resources) {
        AuthData authData = authDataRepository.findById(resources.getId()).orElseGet(AuthData::new);
        ValidationUtil.isNull( authData.getId(),"AuthData","id",resources.getId());
        authData.copy(resources);
        authDataRepository.save(authData);
    }

    @Override
    //@CacheEvict(allEntries = true)
    public void deleteAll(Integer[] ids) {
        for (Integer id : ids) {
            authDataRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<AuthDataDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (AuthDataDto authData : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("姓名", authData.getRealName());
            map.put("性别", authData.getSex());
            map.put("出生日期", authData.getBirthData());
            map.put("身份证号", authData.getIdCard());
            map.put("学校", authData.getSchool());
            map.put("班级", authData.getClasses());
            map.put("专业", authData.getMajor());
            map.put("学号", authData.getStuNo());
            map.put("解答科目", authData.getAnswerSubject());
            map.put("认证状态", authData.getStatus());
            map.put("创建时间", authData.getCreateTime());
            map.put("更新时间", authData.getUpdateTime());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public AuthDataDto findByUserId(Integer id) {
        WxUser wxUser = wxUserRepository.findById(id).orElseGet(WxUser::new);
        ValidationUtil.isNull(wxUser.getId(),"WxUser","id",id);
        AuthData authData = wxUser.getAuthData();
        return authDataMapper.toDto(authData);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createOrUpdateByUserId(AuthData authData, Integer id) {
        WxUser wxUser = wxUserRepository.findById(id).orElseGet(WxUser::new);
        ValidationUtil.isNull( wxUser.getId(),"WxUser","id",wxUser.getId());
        if(wxUser.getAuthData()!=null){
            AuthData data = wxUser.getAuthData();
            authData.setId(data.getId());
            data.copy(authData);
            authDataRepository.save(data);
        }else{
            AuthData saveData = authDataRepository.save(authData);
            wxUser.setAuthData(saveData);
            WxUser saveUser = wxUserRepository.save(wxUser);
            System.out.println("------wxUser------");

            System.out.println(wxUser);
            System.out.println("------saveUser------");
            System.out.println(saveUser);
        }
    }

    @Override
    public Map inquiryById(Integer id) {
        WxUser wxUser = wxUserRepository.findById(id).orElseGet(WxUser::new);
        ValidationUtil.isNull(wxUser.getId(),"WxUser","id",id);
        AuthData authData = wxUser.getAuthData();
        Map<String, Object> map = new HashMap<>();
        map.put("status",authData.getStatus());
        map.put("message",authData.getMessage());
        return map;
    }
}